package com.naiterui.ehp.bs.im.network.transfer;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.naiterui.ehp.bp.domain.PatientInquirer;
import com.naiterui.ehp.bs.im.config.MediaFileConfig;
import com.naiterui.ehp.bs.im.exception.NaiteruiIMException;
import com.naiterui.ehp.bs.im.network.mqtt.MqttClientUtils;
import com.naiterui.ehp.bs.im.network.protocl.*;
import com.naiterui.ehp.bs.im.network.transcode.IMessageTransCoder;
import com.naiterui.ehp.bs.im.remote.IRemoter;
import com.naiterui.ehp.bs.im.repository.PatientInquirerRepository;
import com.naiterui.ehp.bs.im.repository.mongo.MessageDao;
import com.naiterui.ehp.bs.im.utils.Constants;
import com.naiterui.ehp.bs.im.utils.NameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * 负责将医生端的消息发送至微信端
 */
@Service
public class DoctorTransfer implements Transfer {

    /**
     * 日志：<code>LOGGER</code>
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(DoctorTransfer.class);

    /**
     * 远程调用方法封装类
     */
    private final IRemoter remoter;

    /**
     * 多媒体文件配置
     */
    private final MediaFileConfig config;

    /**
     * 消息编/解码对象
     */
    private final IMessageTransCoder messageTransCoder;

    private PatientInquirerRepository patientInquirerRepository;

    /**
     * messageDao：<code>messageDao</code>
     */
    private final MessageDao messageDao;

    public DoctorTransfer(IRemoter remoter, MediaFileConfig config, IMessageTransCoder messageTransCoder, MessageDao messageDao,
                          PatientInquirerRepository patientInquirerRepository) {
        this.remoter = remoter;
        this.config = config;
        this.messageTransCoder = messageTransCoder;
        this.messageDao = messageDao;
        this.patientInquirerRepository = patientInquirerRepository;
    }

    @Override
    public void sendMessage(Message<?> message, boolean isOnline) throws NaiteruiIMException {

//        /** 患者微信端发送消息 */
//        boolean sendWX = null == message.getLastPlatform() || HeaderConstant.HEADER_ORIGIN_PATIENT_WX == message.getLastPlatform();
//        /** 在线视频咨询消息是否推送微信？？？ 目前不推送 */
//        if (sendWX) {
//            this.sendWXMessage(message);
//        }

        /** 患者APP端发送消息 */
//        boolean usePtApp = RedisUtil.keyOps().existsKey(CommonConstant.PT_APP_LOGIN_IN + message.getTo().getId());
//        LOGGER.info("发送消息, usePtApp:{}, isOnline:{}", usePtApp, isOnline);
//        if (usePtApp) {
            // 增加多媒体消息下载地址的域名
            this.addMediaMsgDwnUrl(message);
            // 消息编码
            final String messageStr = this.messageTransCoder.encodeMessage(message);
            // 如果在线直接推送至MQTT，不在线上环节已处理离线消息缓存
            if (isOnline) {
                /*PatientInquirer patientInquirer = patientInquirerRepository.findByInquirerId(message.getTo().getId());
                Long userId = patientInquirer != null ? patientInquirer.getPatientId() : message.getTo().getId();
                MqttClientUtils.publishMessageToClient(NameUtils.ptMsgTopic(userId), messageStr);*/
                MqttClientUtils.publishMessageToClient(NameUtils.ptMsgTopic(message.getTo().getId()), messageStr);
            }
//        }

    }

    private void sendWXMessage(Message<?> message) throws NaiteruiIMException {

        // 传输给WX的消息内容
        String content = "";

        // 转换请求类型
        int type = 0;
        switch (message.getType()) {
            case Constants.MESSAGE_TYPE_TEXT:
                type = Constants.MESSAGE_WEIXIN_SEND_TYPE_TEXT;
                content = message.getContent().toString();
                break;
            case Constants.MESSAGE_TYPE_MEDIA_IMG:
                type = Constants.MESSAGE_WEIXIN_SEND_TYPE_IMAGE;
                Media media = (Media) message.getContent();
                content = media.getPath();
                break;

            default:
                break;
        }
        if (message.getType() == Constants.MESSAGE_TYPE_TEXT) {
            type = Constants.MESSAGE_WEIXIN_SEND_TYPE_TEXT;
            content = message.getContent().toString();
        } else if (message.getType() == Constants.MESSAGE_TYPE_MEDIA_IMG) {
            type = Constants.MESSAGE_WEIXIN_SEND_TYPE_IMAGE;
            Media media = (Media) message.getContent();
            content = media.getPath();
        } else if (message.getType() == Constants.MESSAGE_TYPE_MEDIA_AUDIO) {
            type = Constants.MESSAGE_WEIXIN_SEND_TYPE_RADIO;
            Media media = (Media) message.getContent();
            content = media.getPath();
        } else if (message.getType() == Constants.MESSAGE_TYPE_DRUG) {
            type = Constants.MESSAGE_WEIXIN_SEND_TYPE_DRUG;
            RecommandDrug recommandDrug = (RecommandDrug) message.getContent();
            content = JSON.toJSONString(recommandDrug);
        } else if (message.getType() == Constants.MESSAGE_TYPE_PAID_CONSULT) {
            type = Constants.MESSAGE_WEIXIN_SEND_TYPE_PAID_CONSULT;
            ConsultPaidNotice paidNotice = (ConsultPaidNotice) message.getContent();
            content = paidNotice.getDetail();
        } else if (message.getType() == Constants.MESSAGE_TYPE_DOCTORS_MEDICALRECORD) {
            type = Constants.MESSAGE_WEIXIN_DOCTORS_MEDICALRECORD;
            DoctorsMedicalRecord doctorsMedicalRecord = (DoctorsMedicalRecord) message.getContent();
            content = JSON.toJSONString(doctorsMedicalRecord);
        }

        // 患者微信发送消息
        String messageId = message.getId();
        String batchId = message.getExd() != null ? message.getExd().getBatchId() : "";
        boolean ignoreSession = message.getExd() == null ? false : message.getExd().getIgnoreSession();
        if (ignoreSession) {
            this.remoter.sendMsgToWx(messageId, batchId, type, message.getFrom().getId(), message.getTo().getId(), content, null, true);
        } else {
            this.remoter.sendMsgToWx(messageId, batchId, type, message.getFrom().getId(), message.getTo().getId(), content, message.getSession());
        }

    }

    @Override
    public void sendOfflineMessage(Message<?> message) throws NaiteruiIMException {
        // 增加多媒体消息下载地址的域名
        this.addMediaMsgDwnUrl(message);

        String messageStr;
        if (null == message.getFrom()) {
            // 公告通知类离线缓存
            messageStr = (String) message.getContent();
        } else {
            // 聊天消息类离线缓存
            messageStr = this.messageTransCoder.encodeMessage(message);
        }

        // 如果在线直接推送至MQTT
        MqttClientUtils.publishMessageToClient(NameUtils.drMsgTopic(message.getTo().getId()), messageStr);
    }

    private void addMediaMsgDwnUrl(Message<?> message) {

        // 处理多媒体消息，患者端向医生发送的消息，需要完整的资源下载地址，因此需要拼接上域名
        int type = message.getType();
        if (type == Constants.MESSAGE_TYPE_MEDIA_IMG || type == Constants.MESSAGE_TYPE_MEDIA_AUDIO || type == Constants.MESSAGE_TYPE_MEDIA_VIDEO) {
            // 转换为多媒体消息内容对象
            Media media = (Media) message.getContent();
            media.setPath(this.config.getServerDomain() + media.getPath());
        }
    }

    @Override
    public void handleOfflineMessage(Long userId) {

        // 获取正常离线消息
        List<Message> commonMessages = this.messageDao.getAndRemoveOfflineMessages(Constants.MESSAGE_RESOURCE_PATIENT, userId);
        LOGGER.debug("send offline messages commonMessages INFO;target={},commonMessages size={}", userId,
                     null == commonMessages ? 0 : commonMessages.size());
        // 同步数据(多平台同步)
        List<Message> syncMessages = this.messageDao.getAndRemoveSyncOfflineMessages(Constants.MESSAGE_RESOURCE_DOCTOR, userId);
        LOGGER.debug("send offline messages syncMessages INFO;target={},syncMessages size={}", userId,
                     null == syncMessages ? 0 : syncMessages.size());

        // 没有离线消息需要发送
        if (CollectionUtil.isEmpty(commonMessages) && CollectionUtil.isEmpty(syncMessages)) {
            LOGGER.error(" offline message send INFO ; empty message;");
            return;
        }

        LOGGER.info("send offline messages to dr_{}, commonMessages size is {},syncMessages size is {}", userId,
                    null == commonMessages ? 0 : commonMessages.size(), null == syncMessages ? 0 : syncMessages.size());

        Set<OfflineMessage> targetMessage = new TreeSet<>();
        for (Message tempCommonMessage : commonMessages) {
            try {
                OfflineMessage tempOfflineMessage = new OfflineMessage(tempCommonMessage);
                targetMessage.add(tempOfflineMessage);
            } catch (Exception e) {
                LOGGER.error(" offline message transfer ERROR ; sourceMessage {} ", tempCommonMessage, e);
            }
        }

        if (null != syncMessages && !syncMessages.isEmpty()) {
            for (Message tempSyncMessage : syncMessages) {
                try {
                    OfflineMessage tempOfflineMessage = new OfflineMessage(tempSyncMessage);
                    targetMessage.add(tempOfflineMessage);
                } catch (Exception e) {
                    LOGGER.error(" offline message transfer ERROR ; sourceMessage {} ", tempSyncMessage, e);
                }
            }
        }

        // 迭代离线消息列表进行消息发送
        for (OfflineMessage message : targetMessage) {
            try {
                if (null == message.getRelation()) {
                    LOGGER.warn("send offline message error , empty relation : message {}", message);
                } else if (Constants.MESSAGE_RESOURCE_DOCTOR == message.getRelation()) {
                    // 多平台消息同步
                    this.sendSyncOfflineMessage(message);
                } else if (Constants.MESSAGE_RESOURCE_PATIENT == message.getRelation()) {
                    // 普通离线消息
                    this.sendOfflineMessage(message);
                }
            } catch (NaiteruiIMException e) {
                LOGGER.error("send offline messages to dr_{} failure, exception is {}", userId, e.getMessage());
            }
        }

    }

    /**
     * 发送同步消息到医生端
     */
    public void sendSyncOfflineMessage(Message<?> message) {

        try {
            // 聊天消息类离线缓存
            String messageStr = this.messageTransCoder.encodeMessage(message);
            // 推送MQTT
            MqttClientUtils.publishMessageToClient(NameUtils.drMsgTopic(message.getFrom().getId()), messageStr);

        } catch (Exception e) {
            LOGGER.error("send offline sync messages to doctor {} failure, exception is {}", message.getFrom().getId(), e.getMessage());
        }
    }

}
